/******************************************************************************
 cnome: A C++ source "genes" discover. :-)

 See more details at:

   http://www.codeplex.com/cnome

 The original author site is at: http://www.alemosbarbosa.com/

 Copyright (c) 2008-2010 Alexandre Lemos Barbosa.
 Distributed under the MIT License. (See accompanying file LICENSE-MIT.txt 
 or at http://www.codeplex.com/cnome/license)
 ******************************************************************************/

#include "cnome_config.h"

#include <wave_cnome/cpplexer/cpp_lex_token_cnome.hpp> 
#include <exception>

#include "actions.h"

#include "typedefs.h"
#include "iterator.h"
#include "scopes.h"
#include "symbol.h"
#include "tokens.h"
#include "util.h"
#include "variables.h"

namespace cnome { namespace actions {
using namespace boost::wave;
using namespace scopes;
using namespace util;
using namespace std;

void newClass_Name(iterator first, iterator last) {
    token_t aux = *first;
#if _DEBUG
    const char * auxc = first->get_value().c_str();
#endif
    symbolPtr smb = symbolPtr(new symbol(token_t(T_IDENTIFIER, first->get_value().c_str(), first->get_position()), symbol::other, first.get_cnome_position()));
    smb->set_identifier_type(symbol::T_CLASS_NAME);
    std::string curScope;
    get_scope(curScope, first->get_value().c_str());
    smb->set_scope(get_symbol_scope(curScope.c_str())!=cnome_symbols.end()?get_symbol_scope(curScope.c_str())->second:symbolPtr(static_cast<symbol*>(0)));
    cnome_symbols[smb->to_str()] = smb;
    iterator auxFirst = first;

#if defined(CNOME_DEBUG)
    std::cout << "newClass_Name: " << smb->to_str() << std::endl;
#endif

    if (var::tmplPrms.size()) {  // Is it a class template declaration?
        var::tmplSbl = smb;
        var::tmplSbl->set_identifier_type(symbol::T_TEMPLATE_NAME);
        // Implicity declares the template parameters
        // TODO: handle template parameter variables
        parameter_scope::level_const_iterator end = var::tmplPrms.end(parameter_scope::current);
        for (parameter_scope::level_const_iterator it = var::tmplPrms.begin(parameter_scope::current); it != end; ++it) {
            symbolPtr sybIt = dynamic_cast<parameter_annotation*>(it->second.get_type()->get_annotation().get())->get_symbol_item_ptr();
            sybIt->set_identifier_type(symbol::T_CLASS_NAME);
            sybIt->set_scope(cnome_symbols.find(smb->to_str())!=cnome_symbols.end()?cnome_symbols.find(smb->to_str())->second:symbolPtr(static_cast<symbol*>(0)));
            cnome_symbols[sybIt->to_str()] = sybIt;

#if defined(CNOME_DEBUG)
            std::cout << "newClass_Name: Template Parameter: " << sybIt->to_str() << std::endl;
#endif
        }
    }
}

void newEnum_Name(iterator first, iterator last) {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newEnum_Name: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    symbolPtr smb = symbolPtr(new symbol(token_t(T_IDENTIFIER,first->get_value().c_str(),first->get_position()), symbol::enun_name, first.get_cnome_position()));
    smb->set_identifier_type(symbol::T_ENUM_NAME);
    std::string curScope;
    get_scope(curScope, first->get_value().c_str());
    smb->set_scope(get_symbol_scope(curScope.c_str())!=cnome_symbols.end()?get_symbol_scope(curScope.c_str())->second:symbolPtr());
    cnome_symbols[smb->to_str()] = smb;

#if defined(CNOME_DEBUG)
    std::cout << "newEnum_Name: " << smb->to_str() << std::endl;
#endif
}

void newTypedef_Name(iterator first, iterator last) {
    return;  // TODO: Verify if the change to class_name if enough to handle this case

    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newTypedef_Name: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    // First skip "typedef" token
    if (*first!=T_TYPEDEF) {
        std::cerr << "newTypedef_Name: *first!=T_TYPEDEF" << std::endl; 
        //throw exception("Internal error");
        throw exception();
    }
    first++;  // Skip typedef token
    if (first == last) {
        std::cerr << "newTypedef_Name: first == last" << std::endl; 
        //throw exception("Internal error");
        throw exception();
    }
    iterator prev;
    symbolPtr smb = symbolPtr(new symbol());
    for (prev=first,first++;
        first!=last&&
        *first!=T_SEMICOLON;
    first++) {
        smb->add(symbol(*prev, symbol::other, prev.get_cnome_position()));
        prev=first;
    }
    token_t tk(T_IDENTIFIER,prev->get_value().c_str(),prev->get_position());
    smb->set_identifier_type(symbol::T_TYPEDEF_NAME);
    smb->set_token(tk);
    smb->set_symbol_type(symbol::typedefname);
    smb->set_symbol_status(symbol::declared);

    std::string curScope;
    get_scope(curScope, first->get_value().c_str());
    smb->set_scope(get_symbol_scope(curScope.c_str())!=cnome_symbols.end()?get_symbol_scope(curScope.c_str())->second:symbolPtr(static_cast<symbol*>(0)));
    cnome_symbols[smb->to_str()] = smb;
#if defined(CNOME_DEBUG)
    std::cout << "newTypedef_Name: " << smb->to_str() << std::endl;
#endif
}

void newNamespace_Alias(iterator first, iterator last) {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newNamespace_Alias: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    std::string val;
    std::string val2;
    iterator it;
    for (it=first;it!=last&&(*it)!=T_ASSIGN;it++)
        val += it->get_value().c_str();
    for (it++;it!=last&&(*it)!=T_SEMICOLON;it++)
        val2 += it->get_value().c_str();

    symbolPtr smb = symbolPtr(new symbol(token_t(T_IDENTIFIER,val.c_str(),first->get_position()), symbol::other, first.get_cnome_position()));
    smb->set_identifier_type(symbol::T_NAMESPACE_ALIAS);
    std::string curScope;
    std::string curScope2;
    get_scope(curScope, val.c_str());
    get_scope(curScope2, val2.c_str());
    itSymbolItem its;
    if ((its = cnome_symbols.find(curScope2)) != cnome_symbols.end())
        smb->set_type_symbol(its->second);
    smb->set_scope(get_symbol_scope(curScope.c_str())!=cnome_symbols.end()?get_symbol_scope(curScope.c_str())->second:symbolPtr(static_cast<symbol*>(0)));
    cnome_symbols[smb->to_str()] = smb;
#if defined(CNOME_DEBUG)
    std::cout << "newNamespace_Alias: " << smb->to_str() << std::endl;
#endif
}


void newOriginal_Namespace_Name(iterator first, iterator last) {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newOriginal_Namespace_Name: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    std::string val;
    sblToStr(first, last, val);
    symbolPtr smb = symbolPtr(new symbol(token_t(T_IDENTIFIER,val.c_str(),first->get_position()), symbol::other, first.get_cnome_position()));
    smb->set_identifier_type(symbol::T_ORIGINAL_NAMESPACE_NAME);
    std::string curScope;
    get_scope(curScope, val.c_str());
    smb->set_scope(get_symbol_scope(curScope.c_str())!=cnome_symbols.end()?get_symbol_scope(curScope.c_str())->second:symbolPtr(static_cast<symbol*>(0)));
    cnome_symbols[smb->to_str()] = smb;

#if defined(CNOME_DEBUG)
    std::cout << "newOriginal_Namespace_Name: " << smb->to_str() << std::endl;
#endif
}
void newTemplate_Name(iterator first, iterator last) {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newTemplate_Name: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    // Identify if it is a class or function template
    iterator itSkp;
    bool isClsTmpl = false;
    bool goOut = false;
    for (itSkp = first; !goOut && itSkp!=last; itSkp++)
        switch(*itSkp) {  // TODO: Identify function template
            case T_CLASS:
            case T_STRUCT:
            case T_UNION:            
                isClsTmpl = true;
                goOut = true;
                break;
            default:
                break;
        }
    if (isClsTmpl) {
        first = itSkp;
        first->set_token_id(T_IDENTIFIER);
    }
    std::string curScope;
    get_scope(curScope, first->get_value().c_str());
    itSymbolItem it;
    if ((it = cnome_symbols.find(curScope)) != cnome_symbols.end())
        it->second->set_identifier_type(symbol::T_TEMPLATE_NAME);
    else {  // TODO: Verify if this condition can occurs.
        cnome_symbols[curScope.c_str()] = symbolPtr(new symbol(token_t(T_IDENTIFIER,first->get_value().c_str(),first->get_position()), symbol::other, first.get_cnome_position()));
        cnome_symbols[curScope.c_str()]->set_identifier_type(symbol::T_TEMPLATE_NAME);
        cnome_symbols[curScope.c_str()]->set_scope(get_symbol_scope(curScope.c_str())!=cnome_symbols.end()?get_symbol_scope(curScope.c_str())->second:symbolPtr(static_cast<symbol*>(0)));
    }

#if defined(CNOME_DEBUG)
    std::cout << "newTemplate_Name: " << curScope << std::endl;
#endif

}

void newEnumerator(iterator first, iterator last) {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newEnumerator: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    symbolPtr smb = symbolPtr(new symbol(token_t(T_IDENTIFIER,first->get_value().c_str(),first->get_position()), symbol::enun_name, first.get_cnome_position()));
    std::string curScope;
    get_scope(curScope, first->get_value().c_str());
    smb->set_scope(get_symbol_scope(curScope.c_str())!=cnome_symbols.end()?get_symbol_scope(curScope.c_str())->second:symbolPtr(static_cast<symbol*>(0)));
    cnome_symbols[smb->to_str()] = smb;

#if defined(CNOME_DEBUG)
    std::cout << "newEnumerator: " << smb->to_str() << std::endl;
#endif
}

void newMember(iterator first, iterator last) {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newMember: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    string val;
    std::string strAux;
    adornersT adrns;
    iterator lFirst = first;
    sblAttribute sblAtt = mmbSblToStr(lFirst, last, val, strAux, adrns);
    if (    (sblAtt & Method) //idx!=val.npos && !isPtrToFct
         &&    sglUtil::instance()->get_state()
            != sglUtil::inside_function_body ) {
        newMethod(first,last);
        return;
    }
    std::size_t idx = val.find_last_of(":");
    if (idx!=val.npos)
        val = val.substr(idx+1);
    std::string curScope;
    get_scope(curScope, val.c_str());

#if defined(CNOME_DEBUG)
    std::cout << "newMember: curScope = " << curScope << ", val = " << val << std::endl;
#endif

    itSymbolItem it=cnome_symbols.find(curScope);
    if (it != cnome_symbols.end()) {
        if (    (    it->second->get_position().get_line()==lFirst->get_position().get_line() && 
                    it->second->get_position().get_column()==lFirst->get_position().get_column() )
             || it->second->get_symbol_status()==symbol::declared
             || it->second->get_symbol_status()==symbol::defined)  
            return; // Could be a back track
        else {
            // Already declared
            static string msg = "";
            msg = msg + "Identifier '"+curScope+"' already declared.";


            std::cerr << std::endl << msg<< std::endl;
            std::cerr << (it->second->get_symbol_type()==symbol::member?"member": 
                         (it->second->get_symbol_type()==symbol::method)?"method":"other")
                      <<", "
                      << (it->second->get_symbol_status()==symbol::declared?"declared":
                         (it->second->get_symbol_status()==symbol::defined?"defined":"unknown"))
                      << std::endl;
            std::cerr 
                      << lFirst->get_position().get_file() << "(" 
                      << lFirst->get_position().get_line() << ','
                      << lFirst->get_position().get_column() <<")"
                      << std::endl;

            boost::spirit::classic::throw_(lFirst, static_cast<const char*>(msg.c_str()));
            
        }
    }

    if (!var::typeDecl.size())
        return; // Every data declaration must have a type 

    symbolPtr smb = symbolPtr(new symbol(*lFirst, symbol::other, lFirst.get_cnome_position()));
    if (*smb!=T_IDENTIFIER)
        smb->set_token_id(T_IDENTIFIER);
    if (*var::typeDecl.front()!=T_TYPEDEF)
        smb->set_symbol_type(symbol::member);
    else {
        smb->set_symbol_type(symbol::typedefname);
        smb->set_identifier_type(symbol::T_TYPEDEF_NAME);
    }

    smb->set_scope(get_symbol_scope(curScope.c_str())!=cnome_symbols.end()?get_symbol_scope(curScope.c_str())->second:symbolPtr(static_cast<symbol*>(0)));
    if (!(sblAtt & PtrToFct))
        smb->set_adorners(adrns);

#if defined(CNOME_DEBUG)
    std::cout << "newMember: " << smb->to_str() << ", val = " << val << std::endl;
#endif

    // In the future warning a message about type default to "int"
    size_t suffixSize;
    std::string strTypeDecl;
    if (var::typeDecl.size())
        get_scope(strTypeDecl, var::typeDecl, suffixSize, false);
    else
        if (!(sblAtt & OperatorCvs)) // TODO: Verify if operator is valid without a type
            strTypeDecl="int";

    if (sblAtt & PtrToFct) {
        string val2;
        adornersT::const_iterator it2;
        for (it2 = adrns.begin(); it2 != adrns.end() && *it2 != T_RIGHTPAREN; it2++)
            val2 += it2->get_value().c_str();
        if (it2 != adrns.end()) {
            strTypeDecl = strTypeDecl + val2 + ")";
            suffixSize += val2.size() + 1;
        }
        suffixMethodName(val2);
        strTypeDecl += val2;
        suffixSize += val2.size();
    }
    strTypeDecl += strAux;
    bool foundTypeSymbol = false;
    scopesFromStr scopes(strTypeDecl, suffixSize);
    while (scopes.next_scope().size())
        if ((it=cnome_symbols.find(scopes.current_scope())) != cnome_symbols.end()) {
            foundTypeSymbol = true;
            smb->set_type_symbol(it->second);
#if defined(CNOME_DEBUG)
            std::cout << "member Type: scopes.current_scope() = " << scopes.current_scope() << endl;
            std::cout << "newMember: strTypeDecl = " << strTypeDecl << endl;
#endif
        }    
    if (sblAtt & PtrToFct) {
//--Verify       var::prmVars.clear();  // Now clear all parameters
       if (!foundTypeSymbol)
           smb->set_type_symbol(declPtrToFct(strTypeDecl, first)); // Declare the pointer to function symbol
    }

    cnome_symbols[smb->to_str()] = smb;
}

void enter_scope(iterator first, iterator last) {
    std::string val;
    sblToStr(first, last, val);
    var::scopeSuffixSize += val.size();

    scopes::enter_scope(val,first);
}

void leaveScope(iterator first, iterator last) {
#if defined(CNOME_DEBUG)
    std::string oldScp;
    get_scope(oldScp);
#endif
    if (var::scope.size()) {
        var::scope.pop_back();
    }

#if defined(CNOME_DEBUG)
    std::string newScp;
    get_scope(newScp);
    std::cout << "leaveScope: " << oldScp << " to " << newScp << endl;
#endif
}
void scopeIsAbsolut(iterator first, iterator last) {
    var::isScopeAbsolut = true;
}

void enterMethodScp(iterator first, iterator last) {
    string val;
    string suf;

    first = var::lastDeclaratorId.first;
    last = var::lastDeclaratorId.second;

    sblToStr(first, last, val);
    suffixMethodName(suf);
    val += suf;
    std::string oldScp;
    get_scope(oldScp,val.c_str());
    itSymbolItem it;
    if ((it = cnome_symbols.find(oldScp)) != cnome_symbols.end())
        var::mthScope = it->second;
    else {
        token_t tk = *first;
        if (val.size()) {
            tk.set_value(val.c_str());
            var::mthScope = symbolPtr(new symbol(tk, symbol::other, first.get_cnome_position()));
            itSymbolItem it;
            if ((it=get_symbol_scope(oldScp.c_str())) != cnome_symbols.end())
                var::mthScope->set_scope(it->second);
        }
    }
    scopes::enter_scope(val, first);
#if defined(CNOME_DEBUG)
    std::string newScp;
    get_scope(newScp);
    std::cout << "enterMethodScp: val = " << val << endl;
    std::cout << "enterMethodScp: " << newScp << " from " << oldScp << endl;
#endif
    declareTmplPrms(first, last);
}

void enterScopeMth(iterator first, iterator last) {
   if (!var::mthScope) {
#if defined(CNOME_DEBUG)
    std::cout << "enterScopeMth: Error: var::mthScope undefined" << endl;
#endif
        return;
    }
    
    std::string val = var::mthScope->get_value().c_str();
    const char* pc = val.c_str();
    std::size_t idx = val.rfind("::");
    if (idx != val.npos)
        val = val.substr(idx+2);
    pc = val.c_str();
    std::string curScp;
    get_scope(curScp,val.c_str());
    pc = curScp.c_str();

#if defined(CNOME_DEBUG)
    std::cout << "enterScopeMth: val = " << val << endl;
    std::cout << "enterScopeMth: " << curScp << endl;
#endif

    itSymbolItem it;
    if ((it = cnome_symbols.find(curScp)) != cnome_symbols.end())
        var::scope.push_back(it->second);
    else {  // TODO: Review. 
        pc = var::mthScope->get_value().c_str();
        var::scope.push_back(var::mthScope);
    }

#if defined(CNOME_DEBUG)
    std::cout << "enterScopeMth: val = " << val << endl;
#endif

}

void newMethod(iterator first, iterator last) {
    newMethodImpl(first, last, false);
}

void newMethodImpl(iterator first, iterator last, bool isParameterDeclaration) {

    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newMethod: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    string val;
    string mthName;
    adornersT adrns;
    sblAttribute sblAtt = mtdSblToStr(first, last, val, mthName, adrns);

    std::string curScope;
    get_scope(curScope, mthName.c_str());
    scopeT tmplPrms;
    adornersT auxAdorners;
    suffixMethodName(val, tmplPrms, &auxAdorners);
    if (sblAtt&TypeDefDcl) {
        while (auxAdorners.size()) {
            adrns.push_back(auxAdorners.back());
            auxAdorners.pop_back();
        }
        if (sblAtt&MethodConst)
            adrns.push_back(token_t(T_CONST, "const", token_t::position_type()));
    }
    else {
        curScope += val;
        if (sblAtt&MethodConst)
            curScope += "const";
    }
    std::string newScope = mthName + val + (!(sblAtt&TypeDefDcl)&&(sblAtt&MethodConst)?"const":"");

    bool reDeclaration;
    bool isDataMember;
    itSymbolItem it = verifyMethodName(first, curScope, isDataMember, reDeclaration);
    if (isDataMember) {   // Change it to method
        it->second->set_symbol_type(symbol::method);
        return;
    }

    std::size_t idx = mthName.find_last_of(":.");
    if (idx!=mthName.npos)
        mthName = mthName.substr(idx+1);
    std::string mthNameFull = mthName + val + (!(sblAtt&TypeDefDcl)&&(sblAtt&MethodConst)?"const":""); 

    symbolPtr smb = symbolPtr(new symbol(token_t(T_IDENTIFIER, ((sblAtt&TypeDefDcl)?mthName:mthNameFull).c_str(),first->get_position()), (sblAtt&TypeDefDcl)?symbol::typedefname:symbol::method, first.get_cnome_position()));
    smb->set_scope(get_symbol_scope(curScope.c_str())!=cnome_symbols.end()?get_symbol_scope(curScope.c_str())->second:symbolPtr(static_cast<symbol*>(0)));
    if (sblAtt&TypeDefDcl)
        smb->set_identifier_type(symbol::T_TYPEDEF_NAME);
    smb->set_adorners(adrns);
    if (var::tmplPrms.size()) {
        smb->set_inners(var::tmplSbl->get_inners());
        var::tmplSbl = smb;
    }

    // Check for constructor declaration
    bool ctorDecl = isCtorDecl(curScope);
    // In the future warning a message about type default to "int"
    size_t suffixSize=0;
    std::string strTypeDecl;
    if (var::typeDecl.size())
        get_scope(strTypeDecl, var::typeDecl, suffixSize);
    else if (!ctorDecl && !(sblAtt & OperatorCvs))
        strTypeDecl="int";

    scopesFromStr scopes(strTypeDecl, suffixSize);
    while (scopes.next_scope().size()) {
        itSymbolItem it;
        if ((it=cnome_symbols.find(scopes.current_scope())) != cnome_symbols.end()) {
            smb->set_type_symbol(it->second);
#if defined(CNOME_DEBUG)
            std::cout << "member Type: scopes.current_scope() = " << scopes.current_scope() << endl;
            std::cout << "newMethod: strTypeDecl = " << strTypeDecl << endl;
#endif
        }    
    }
    if (!verifyCtorDecl(ctorDecl, smb, first))  // 
        return; // TODO: Analyze if it ok because this line will never run because if verifyCtorDecl fails a exception is thrown
    if (!reDeclaration) {
        string smbStr(smb->to_str());
        it = cnome_symbols.find(smbStr.c_str());
        if (it == cnome_symbols.end()) {
            cnome_symbols[smbStr.c_str()] = smb;
            it = cnome_symbols.find(smbStr.c_str());
        }
        adjustTmplPrms(smb);
        adjustPrmVars(smb);
        declareParameters(it);
    }
    else if (ctorDecl || (!ctorDecl && verifyReturnType(it, smb, first))) {  // Is the return value different?
        adjustTmplPrms(smb);
        adjustPrmVars(smb);
        if (!compareParameters(it, smb, first))
            return;
    }

#if defined(CNOME_DEBUG)
    std::cout << "newMethod: " << smb->to_str() << std::endl;
#endif

    if (last != iterator::end && *last == T_SEMICOLON)
        adjustTmplPrms(first, last);
    scopes::enter_scope(newScope,first);
}

void defMethod(iterator first, iterator last) {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "defMethod: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    std::string curScope;
    get_scope(curScope);

    if (!curScope.size())  // Method name is null
        return;

#if defined(CNOME_DEBUG)
    std::cout << "defMethod: " << curScope << std::endl;
#endif

    itSymbolItem it;
    if ((it=cnome_symbols.find(curScope)) != cnome_symbols.end())
        it->second->set_symbol_status(symbol::defined);
    else {
        // Already declared
        static string msg = "";
        msg = msg + "Identifier '"+curScope+"' isn't declared.";

        std::cerr << std::endl << msg<< std::endl;
        std::cerr 
                  << first->get_position().get_file() << "(" 
                  << first->get_position().get_line() << ','
                  << first->get_position().get_column() <<")"
                  << std::endl;

        boost::spirit::classic::throw_(first, static_cast<const char*>(msg.c_str()));
            
    }
}

void clearPrmLevel(iterator first, iterator last) {
    try {
        var::prms.clearPrmLevel();
    }
    catch (...) {
         boost::spirit::classic::throw_(first, "cnome::actions::clearPrmLevel");
    }
}

void newParenMethod(iterator first, iterator last) {
    first->set_annotation(token_annotation_ptrT(new parenthesis_annotation(var::prms.get_prmLevel(), parenthesis_annotation::method_type)));

#if defined(CNOME_DEBUG)
    std::cout << "newParenMethod: var::prms.get_prmLevel() " << var::prms.get_prmLevel() << std::endl;
#endif
}

void newTmplPrm(iterator first, iterator last) {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newTmplPrm: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    std::string val;
    for (iterator itv=first;itv!=last;itv++)
        val += itv->get_value().c_str();

#if defined(CNOME_DEBUG)
    std::cout << "newTmplPrm: " << val << std::endl;
#endif

    // Verify if the parameter is already declared in this parameters declaration list
    // TODO: handle template parameter variables
    for (parameter_scope::level_const_iterator it = var::tmplPrms.begin(parameter_scope::current); it != var::tmplPrms.end(parameter_scope::current); ++it) {
        if (it->second.get_var() && it->second.get_var()->get_value() == val.c_str()) {
            // Already declared
            static string msg = "";
            msg = msg + "Template parameter '"+val+"' duplicated in the same parameter list.";

            std::cerr << std::endl << msg<< std::endl;
            std::cerr 
                      << first->get_position().get_file() << "(" 
                      << first->get_position().get_line() << ','
                      << first->get_position().get_column() <<")"
                      << std::endl;

            boost::spirit::classic::throw_(first, static_cast<const char*>(msg.c_str()));
        }
    }
    token_t tk = *first;
    symbolPtr tmp = symbolPtr(new symbol(*first, symbol::template_parameter, first.get_cnome_position()));
    first->set_annotation(token_annotation_ptrT(new parameter_annotation(tmp, tmp->get_identifier_type(), var::tmplPrms.get_pos(), template_parameter)));
    var::tmplPrms.add_parameter(*tmp);
}

void newMethodPrm(iterator first, iterator last) {
    try {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newPrm: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    if (first == last) 
        return;

    adornersT auxAd;
    iterator itPmt=last;
    std::string val;
    for (iterator itv=first;itv!=last;itv++) {
        switch (*itv) {
            case T_IDENTIFIER:
//                    if (itPmt == last)
                    itPmt = itv;
                if (val.size() && (isalnum(val[val.size()-1]) || val[val.size()-1]=='_')) 
                    val += ' ';
                val += itv->get_value().c_str();
                break;
            case T_AND:
            case T_STAR:
            case T_CONST:
                auxAd.push_back(*itv);
                break;
            case T_CLASS:
            case T_ENUM:   // TODO: Implement a test to avoid the mix and repeat of this tokens
            case T_STRUCT: // TODO: handle "struct a* b;" declaration better
            case T_UNION:
                break;
            case T_CHAR:
            case T_WCHART:
            case T_BOOL:
            case T_SHORT:
            case T_INT:
            case T_LONG:
            case T_SIGNED:
            case T_UNSIGNED:
            case T_FLOAT:
            case T_DOUBLE:
            case T_VOID:
                if (    val.size() && (isalnum(val[val.size()-1]) || val[val.size()-1]=='_') 
                     && itv->get_value().size() && (    isalnum(itv->get_value()[itv->get_value().size()-1])
                                                     || itv->get_value()[itv->get_value().size()-1]=='_' ) )
                    val += ' ';
                val += itv->get_value().c_str();
                auxAd.push_back(*itv);
                itPmt = itv;
                break;
            case T_ELLIPSIS:
                val += itv->get_value().c_str();
                itPmt = itv;
                break;
            default: // TODO: Verify if this option is OK
                if (    val.size() && (isalnum(val[val.size()-1]) || val[val.size()-1]=='_') 
                     && itv->get_value().size() && (    isalnum(itv->get_value()[itv->get_value().size()-1])
                                                     || itv->get_value()[itv->get_value().size()-1]=='_' ) )
                    val += ' ';
                val += itv->get_value().c_str();
                auxAd.push_back(*itv);
                break;
        }
    }
    appendAdorners(val, auxAd);

    itSymbolItem psmb(cnome_symbols.end());
    // In the future warning a message about type default to "int"
    std::string strTypeDecl;
    if (*first == T_ELLIPSIS)
        strTypeDecl = "...";
    else if (!var::typeDecl.size())
        strTypeDecl="int";
    else {
        //get_scope(strTypeDecl, var::typeDecl);  // TODO (alb) 27oct2010: After validating the change below, remove this line
        strTypeDecl = var::typeDecl.back()->to_str();
        appendAdorners(strTypeDecl, var::typeDecl.back()->get_adorners());
    }

    string auxt;
    if (strTypeDecl.size() < val.size() || (auxt=strTypeDecl.substr(strTypeDecl.size()-val.size())) != val) {
        cerr << "newPrm: Error : " 
             << first->get_position().get_file() << "(" 
             << first->get_position().get_line() << ','
             << first->get_position().get_column() <<"): "
             << std::endl;
        boost::spirit::classic::throw_(first, "Internal compiler error");
    }
    scopesFromStr scopes(strTypeDecl, val.size());
    while (scopes.next_scope().size()) {
        itSymbolItem it;
        if ((it=findTypeDecl(scopes.current_scope(), first)) != cnome_symbols.end()) {
            psmb = it;
#if defined(CNOME_DEBUG)
            std::cout << "parameter Type: scopes.current_scope() = " << scopes.current_scope() << endl;
            std::cout << "newPrm: strTypeDecl = " << strTypeDecl << endl;
#endif
        }    
    }

    if (psmb != cnome_symbols.end()) {
        itPmt->set_annotation(token_annotation_ptrT(new parameter_annotation(psmb->second, psmb->second->get_identifier_type(), var::prms.get_pos())));
        var::prms.add_parameter(*itPmt);
    }

#if defined(CNOME_DEBUG)
    std::cout << "newPrm: Current Parameters:"<< endl;

    for (parameter_scope::level_const_iterator it = var::prms.begin(parameter_scope::current); it != var::prms.end(parameter_scope::current); it++) {
        symbolPtr sybIt(dynamic_cast<parameter_annotation*>(it->second.get_type()->get_annotation().get())->get_symbol_item_ptr());
        std::cout << sybIt->to_str() << " : " 
                  << (sybIt->get_type_symbol()?sybIt->get_type_symbol()->to_str():"");
        if (it->second. get_type()->get_annotation()) {
            std::cout << ", level : " << var::prms.get_level();
        }
        std::cout << endl;
    }
#endif
    }
    catch(exception& e) {
        throw cnome_parser_error(first.base(), e.what());
    }
    catch(...) {
        throw cnome_parser_error(first.base(), "unknown error");
    }
}

void newTemplatePrm(iterator first, iterator last) {
    try {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newPrm: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    if (first == last) 
        return;

    adornersT auxAd;
    iterator itPmt=last;
    std::string val;
    for (iterator itv=first;itv!=last;itv++) {
        switch (*itv) {
            case T_IDENTIFIER:
//                    if (itPmt == last)
                    itPmt = itv;
                if (val.size() && (isalnum(val[val.size()-1]) || val[val.size()-1]=='_')) 
                    val += ' ';
                val += itv->get_value().c_str();
                break;
            case T_AND:
            case T_STAR:
            case T_CONST:
                auxAd.push_back(*itv);
                break;
            case T_CLASS:
            case T_ENUM:   // TODO: Implement a test to avoid the mix and repeat of this tokens
            case T_STRUCT: // TODO: handle "struct a* b;" declaration better
            case T_UNION:
                break;
            case T_CHAR:
            case T_WCHART:
            case T_BOOL:
            case T_SHORT:
            case T_INT:
            case T_LONG:
            case T_SIGNED:
            case T_UNSIGNED:
            case T_FLOAT:
            case T_DOUBLE:
            case T_VOID:
                if (    val.size() && (isalnum(val[val.size()-1]) || val[val.size()-1]=='_') 
                     && itv->get_value().size() && (    isalnum(itv->get_value()[itv->get_value().size()-1])
                                                     || itv->get_value()[itv->get_value().size()-1]=='_' ) )
                    val += ' ';
                val += itv->get_value().c_str();
                auxAd.push_back(*itv);
                itPmt = itv;
                break;
            case T_ELLIPSIS:
                val += itv->get_value().c_str();
                itPmt = itv;
                break;
            default: // TODO: Verify if this option is OK
                if (    val.size() && (isalnum(val[val.size()-1]) || val[val.size()-1]=='_') 
                     && itv->get_value().size() && (    isalnum(itv->get_value()[itv->get_value().size()-1])
                                                     || itv->get_value()[itv->get_value().size()-1]=='_' ) )
                    val += ' ';
                val += itv->get_value().c_str();
                auxAd.push_back(*itv);
                break;
        }
    }
    appendAdorners(val, auxAd);

    itSymbolItem psmb(cnome_symbols.end());
    // In the future warning a message about type default to "int"
    std::string strTypeDecl;
    if (*first == T_ELLIPSIS)
        strTypeDecl = "...";
    else if (!var::typeDecl.size())
        strTypeDecl="int";
    else {
        get_scope(strTypeDecl, var::typeDecl);
    }

    string auxt;
    if (strTypeDecl.size() < val.size() || (auxt=strTypeDecl.substr(strTypeDecl.size()-val.size())) != val) {
        cerr << "newPrm: Error : " 
             << first->get_position().get_file() << "(" 
             << first->get_position().get_line() << ','
             << first->get_position().get_column() <<"): "
             << std::endl;
        boost::spirit::classic::throw_(first, "Internal compiler error");
    }
    scopesFromStr scopes(strTypeDecl, val.size());
    while (scopes.next_scope().size()) {
        itSymbolItem it;
        if ((it=findTypeDecl(scopes.current_scope(), first)) != cnome_symbols.end()) {
            psmb = it;
#if defined(CNOME_DEBUG)
            std::cout << "parameter Type: scopes.current_scope() = " << scopes.current_scope() << endl;
            std::cout << "newPrm: strTypeDecl = " << strTypeDecl << endl;
#endif
        }    
    }

    if (psmb != cnome_symbols.end()) {
        itPmt->set_annotation(token_annotation_ptrT(new parameter_annotation(psmb->second, psmb->second->get_identifier_type(), var::tmplPrms.get_pos())));
        var::tmplPrms.add_parameter(*itPmt);
    }

#if defined(CNOME_DEBUG)
    std::cout << "newPrm: Current Parameters:"<< endl;

    for (parameter_scope::const_iterator it = var::prms.begin(); it != var::tmplPrms.end(); it++) {
        if (it->second.get_type()->get_annotation()) {
            if (var::tmplPrms.get_level(it) != var::tmplPrms.get_prmLevel()) {
                break;
            }
        }
        symbolPtr sybIt(dynamic_cast<parameter_annotation*>(it->second.get_type()->get_annotation().get())->get_symbol_item_ptr());
        std::cout << sybIt->to_str() << " : " 
                  << (sybIt->get_type_symbol()?sybIt->get_type_symbol()->to_str():"");
        if (it->second.get_type()->get_annotation()) {
            std::cout << ", level : " << var::tmplPrms.get_level(it);
        }
        std::cout << endl;
    }
#endif
    }
    catch(exception& e) {
        throw cnome_parser_error(first.base(), e.what());
    }
    catch(...) {
        throw cnome_parser_error(first.base(), "unknown error");
    }
}

void newPrm(iterator first, iterator last) {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newPrm: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }
    if (var::parameterType == method_parameter) {
        newMethodPrm(first, last);
    }
    else if (var::parameterType == template_parameter) {
        newTemplatePrm(first, last);
    }
    else {
        throw cnome_parser_error(first.base(), "newPrm: invalid var::parameterType");
    }
}

void newMethodPrmVar(iterator first, iterator last) {
    try {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newMethodPrmVar: Called inside look_ahead operation" << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    int prmpos =  var::prms.get_prmNums() - 1;

    bool isPtrToFct = false; // Is pointer to function?

    int lInsideParenthesis = 0;
    adornersT auxAd;
    iterator itPmt=last;
    iterator itLastId=last;
    std::string val;
    for (iterator itv=first;itv!=last;itv++) {
        switch (*itv) {
            case T_IDENTIFIER: 
                {
#ifdef _DEBUG		  
                token_t& tk = *itv;
#endif		
                std::string curScope;
                get_scope(curScope, itv->get_value().c_str());
                itSymbolItem it;
                if ((it=cnome_symbols.find(curScope)) != cnome_symbols.end() &&
                    it->second->get_symbol_type() == symbol::template_variable) {
                    auxAd.push_back(*itv);
                }
                else if (!isPtrToFct) {
//                        if (itPmt == last)
                        itPmt = itv;
                    val += itv->get_value().c_str();
                    itLastId = itv;
                } 
                else {
                    identifier_annotation* id_ann = dynamic_cast<identifier_annotation*>(itv->get_annotation().get());
                    if (id_ann->get_id_type() != symbol::NONE)
                       auxAd.push_back(*itv);
                }
                               }
                break;
            case T_AND:
            case T_STAR:
            case T_CONST:
                auxAd.push_back(*itv);
                break;
            case T_LEFTPAREN:
                if (itv->get_annotation()) {
                    isPtrToFct = true;
                    if (!lInsideParenthesis) {
                        //newMember(first, last);
                        ; // TODO (alb): Handle ptrtofct correctly. For now do nothing.
                    }
                }
                auxAd.push_back(*itv);
                ++lInsideParenthesis;
                break;
            case T_RIGHTPAREN:
                auxAd.push_back(*itv);
                --lInsideParenthesis;
                break;
            case T_LEFTBRACKET:
            case T_RIGHTBRACKET:
                auxAd.push_back(*itv);
                break;
            case T_ELLIPSIS:
                val += itv->get_value().c_str();
                itPmt = itv;
                break;
            default: // TODO: Verify if this option is OK
                val += itv->get_value().c_str();
                break;
        }
    }

#if defined(CNOME_DEBUG)
    std::cout << "itPmt: " << itPmt->get_value() << std::endl;
#endif

    std::ostringstream ost;
    if (itPmt == last && *first != T_ELLIPSIS) {  // Probably an abstract_declarator
        ost << (unsigned int) prmpos;
        val = ost.str();
    }

    std::string scp;
    get_scope(scp,val.c_str());
    val = scp;

#if defined(CNOME_DEBUG)
    std::cout << "newMethodPrmVar: " << val << std::endl;
#endif

    // Verify if the parameter is already declared in this parameters declaration list
    for (parameter_scope::level_const_iterator it = var::prms.begin(parameter_scope::current); it!=var::prms.end(parameter_scope::current); ++it)
        if (it->second.get_var() && it->second.get_var()->get_value() == val.c_str()) {
            // Already declared
            static string msg = "";
            msg = msg + "Parameter '" + val + "' duplicated in the same parameter list.";

            std::cerr << std::endl << msg<< std::endl;
            std::cerr 
                      << first->get_position().get_file() << "(" 
                      << first->get_position().get_line() << ','
                      << first->get_position().get_column() <<")"
                      << std::endl;

            boost::spirit::classic::throw_(first, static_cast<const char*>(msg.c_str()));
        }

    symbolPtr smb;
    
    smb = symbolPtr(new symbol(*itPmt, symbol::other, first.get_cnome_position()));
    if (itPmt == last) {  // Probably an abstract_declarator
        // Note: The position of parameter will be fictional and probably 
        //       will be equal the position of the following token (a comma or 
        //       a leftparen. This occurs because the parameter variable isn't 
        //       declared in abstract declaration and a position must be choose 
        //       for the parameter.
        // ALB : 06jan06
        smb->set_value(ost.str().c_str());
        smb->set_token_id(T_IDENTIFIER);
    }

    if (auxAd.size())
        smb->set_adorners(auxAd);

    // In the future warning a message about type default to "int"
    std::size_t suffixSize;
    std::string strTypeDecl;
    if (*first == T_ELLIPSIS) {
        strTypeDecl = "...";
        suffixSize = 3;
    }
    else if (var::typeDecl.size())
        get_scope(strTypeDecl, var::typeDecl, suffixSize, false);
    else {
        strTypeDecl = "int";
        suffixSize = 3;
    }
    scopesFromStr scopes(strTypeDecl, suffixSize);
    while (scopes.next_scope().size()) {
        itSymbolItem it;
        if ((it=cnome_symbols.find(scopes.current_scope())) != cnome_symbols.end()) {
            smb->set_type_symbol(it->second);
#if defined(CNOME_DEBUG)
            std::cout << "parameter Type: scopes.current_scope() = " << scopes.current_scope() << endl;
            std::cout << "newMethodPrmVar: strTypeDecl = " << strTypeDecl << endl;
#endif
        }    
    }
    smb->set_parameter_position(prmpos);

    itPmt->set_annotation(token_annotation_ptrT(new parameter_annotation(smb, smb->get_identifier_type(), var::prms.get_pos())));

    var::prms.add_parameter_var(*itPmt);

    if (itLastId != last) {
        if (!itLastId->get_annotation()) {
            itLastId->set_annotation(token_annotation_ptrT(new parameter_annotation(symbolPtr(), symbol::NONE, var::prms.get_pos())));
        }
        else if (itLastId->get_annotation()->get_tag() == IDENTIFIERANNOTATION ) {
            itLastId->set_annotation(token_annotation_ptrT(
                new parameter_annotation(
                    dynamic_cast<identifier_annotation*>(itLastId->get_annotation().get())->get_symbol_item_ptr(), 
                    dynamic_cast<identifier_annotation*>(itLastId->get_annotation().get())->get_id_type(),
                    var::prms.get_pos())));
        }
    }

#if defined(CNOME_DEBUG)
    std::cout << "newMethodPrmVar: prmVars items:" << std::endl;
    for (parameter_scope::level_const_iterator it = var::prms.begin(parameter_scope::current); it != var::prms.end(parameter_scope::current); it++) {
        if (!it->second.get_var()) {
            continue;
        }
        symbolPtr sybIt(dynamic_cast<parameter_annotation*>(it->second.get_var()->get_annotation().get())->get_symbol_item_ptr());
        std::cout << sybIt->to_str() << " : " 
                  << (sybIt->get_type_symbol()?sybIt->get_type_symbol()->to_str():"");
        if (it->second.get_var()->get_annotation()) {
            std::cout << ", level : " << var::prms.get_level();
        }
        std::cout << endl;
    }
#endif
    }
    catch(exception& e) {
        throw cnome_parser_error(first.base(), e.what());
    }
    catch(...) {
        throw cnome_parser_error(first.base(), "unknown error");
    }
}

void newTemplatePrmVar(iterator first, iterator last) {
    try {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newTmplPrmVar: Called inside look_ahead operation" << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }

    int prmpos =  var::tmplPrms.get_prmNums() - 1;
    bool isPtrToFct = false; // Is pointer to function?

    int lInsideParenthesis = 0;
    adornersT auxAd;
    iterator itPmt=last;
    iterator itLastId=last;
    std::string val;
    for (iterator itv=first;itv!=last;itv++) {
        switch (*itv) {
            case T_IDENTIFIER:
                if (!isPtrToFct) {
//                        if (itPmt == last)
                        itPmt = itv;
                    val += itv->get_value().c_str();
                    itLastId = itv;
                } 
                else {
                    identifier_annotation* id_ann = dynamic_cast<identifier_annotation*>(itv->get_annotation().get());
                    if (id_ann->get_id_type() != symbol::NONE)
                       auxAd.push_back(*itv);
                }
                break;
            case T_AND:
            case T_STAR:
            case T_CONST:
                auxAd.push_back(*itv);
                break;
            case T_LEFTPAREN:
                if (itv->get_annotation()) {
                    isPtrToFct = true;
                    if (!lInsideParenthesis) {
                        //newMember(first, last);
                        ; // TODO (alb): Handle ptrtofct correctly. For now do nothing.
                    }
                }
                auxAd.push_back(*itv);
                ++lInsideParenthesis;
                break;
            case T_RIGHTPAREN:
                auxAd.push_back(*itv);
                --lInsideParenthesis;
                break;
            case T_LEFTBRACKET:
            case T_RIGHTBRACKET:
                auxAd.push_back(*itv);
                break;
            default: // TODO: Verify if this option is OK
                val += itv->get_value().c_str();
                break;
        }
    }

#if defined(CNOME_DEBUG)
    std::cout << "itPmt: " << itPmt->get_value() << std::endl;
#endif

    std::ostringstream ost;
    if (itPmt == last && *first != T_ELLIPSIS) {  // Probably an abstract_declarator
        ost << (unsigned int) prmpos;
        val = ost.str();
    }

    std::string scp;
    get_scope(scp,val.c_str());
    val = scp;

#if defined(CNOME_DEBUG)
    std::cout << "newTmplPrmVar: " << val << std::endl;
#endif

    // Verify if the parameter is already declared in this parameters declaration list
    for (parameter_scope::level_const_iterator it = var::tmplPrms.begin(parameter_scope::current); it != var::tmplPrms.end(parameter_scope::current); ++it)
        if (it->second.get_var() && it->second.get_var()->get_value() == val.c_str()) {
            // Already declared
            static string msg = "";
            msg = msg + "Parameter '"+val+"' duplicated in the same parameter list.";

            std::cerr << std::endl << msg<< std::endl;
            std::cerr 
                      << first->get_position().get_file() << "(" 
                      << first->get_position().get_line() << ','
                      << first->get_position().get_column() <<")"
                      << std::endl;

            boost::spirit::classic::throw_(first, static_cast<const char*>(msg.c_str()));
        }

    symbolPtr smb;
    if (*first == T_ELLIPSIS)
        smb = symbolPtr(new symbol(*first, symbol::template_variable, first.get_cnome_position()));
    else {
        smb = symbolPtr(new symbol(*itPmt, symbol::template_variable, first.get_cnome_position()));
        if (itPmt == last) {  // Probably an abstract_declarator
            // Note: The position of parameter will be fictional and probably 
            //       will be equal the position of the following token (a comma or 
            //       a leftparen. This occurs because the parameter variable isn't 
            //       declared in abstract declaration and a position must be choose 
            //       for the parameter.
            // ALB : 06jan06
            smb->set_value(ost.str().c_str());
            smb->set_token_id(T_IDENTIFIER);
        }
    }

    if (auxAd.size())
        smb->set_adorners(auxAd);

    // In the future warning a message about type default to "int"
    std::size_t suffixSize;
    std::string strTypeDecl;
    if (*first == T_ELLIPSIS) {
        strTypeDecl = "...";
        suffixSize = 3;
    }
    else if (var::typeDecl.size())
        get_scope(strTypeDecl, var::typeDecl, suffixSize, false);
    else {
        strTypeDecl = "int";
        suffixSize = 3;
    }
    scopesFromStr scopes(strTypeDecl, suffixSize);
    while (scopes.next_scope().size()) {
        itSymbolItem it;
        if ((it=cnome_symbols.find(scopes.current_scope())) != cnome_symbols.end()) {
            smb->set_type_symbol(it->second);
#if defined(CNOME_DEBUG)
            std::cout << "parameter Type: scopes.current_scope() = " << scopes.current_scope() << endl;
            std::cout << "newTmplPrmVar: strTypeDecl = " << strTypeDecl << endl;
#endif
        }    
    }
    smb->set_parameter_position((int)prmpos);

    itPmt->set_annotation(token_annotation_ptrT(new parameter_annotation(smb, smb->get_identifier_type(), var::tmplPrms.get_pos(), template_parameter)));

    var::tmplPrms.add_parameter_var(*itPmt);

    if (itLastId != last) {
        if (!itLastId->get_annotation()) {
            itLastId->set_annotation(token_annotation_ptrT(new parameter_annotation(symbolPtr(), symbol::NONE, var::tmplPrms.get_pos(), template_parameter)));
        }
        else if (itLastId->get_annotation()->get_tag() == IDENTIFIERANNOTATION ||
            itLastId->get_annotation()->get_tag() == PARAMETERANNOTATION) {
            itLastId->set_annotation(token_annotation_ptrT(
                new parameter_annotation(
                    dynamic_cast<identifier_annotation*>(itLastId->get_annotation().get())->get_symbol_item_ptr(), 
                    dynamic_cast<identifier_annotation*>(itLastId->get_annotation().get())->get_id_type(),
                    var::tmplPrms.get_pos(), template_parameter)));
        }
    }

#if defined(CNOME_DEBUG)
    std::cout << "newTemplatePrmVar: tmplPrmVars items:" << std::endl;
    for (parameter_scope::level_const_iterator it = var::tmplPrms.begin(parameter_scope::current); it != var::tmplPrms.end(parameter_scope::current); it++) {
        if (!it->second.get_var()) {
            continue;
        }
        //if (it->second.get_var()->get_annotation()) {
        //    if (var::tmplPrms.get_level(it) > var::tmplPrms.get_prmLevel()) 
        //        continue;
        //    else if (var::tmplPrms.get_level(it) < var::tmplPrms.get_prmLevel()) 
        //        break;
        //}
        symbolPtr sybIt(dynamic_cast<parameter_annotation*>(it->second.get_var()->get_annotation().get())->get_symbol_item_ptr());
        std::cout << sybIt->to_str() << " : " 
                  << (sybIt->get_type_symbol()?sybIt->get_type_symbol()->to_str():"");
        if (it->second.get_var()->get_annotation()) {
            std::cout << ", level : " << var::tmplPrms.get_level();
        }
        std::cout << endl;
    }
#endif
    }
    catch(exception& e) {
        throw cnome_parser_error(first.base(), e.what());
    }
    catch(...) {
        throw cnome_parser_error(first.base(), "unknown error");
    }
}

void newPrmVar(iterator first, iterator last) {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newPrm: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }
    if (var::parameterType == method_parameter) {
        newMethodPrmVar(first, last);
    }
    else if (var::parameterType == template_parameter) {
        newTemplatePrmVar(first, last);
    }
    else {
        throw cnome_parser_error(first.base(), "newPrmVar: invalid var::parameterType");
    }
}

void newPtfPrmVar(iterator first, iterator last) {
    if (sglLookahead::instance()->get_is_looking()) {
#if defined(CNOME_DEBUG)
    std::cout << "newPrm: Called inside look_ahead operation" 
        << std::endl;
#endif
        return;  // Do nothing during a lookahead
    }
    // TODO (ALB): Implement code
    // 06aug2010
    //if (var::parameterType == method_parameter) {
    //	newMethodPrmVar(first, last);
    //}
    //else if (var::parameterType == template_parameter) {
    //	newTemplatePrmVar(first, last);
    //}
    //else {
    //	throw cnome_parser_error(first.base(), "newPrmVar: invalid var::parameterType");
 //   }
    newMethodImpl(first,last, true);
}

void cancelPrmVar(iterator first, iterator last) {
    for (parameter_scope::level_const_iterator it = var::prms.begin(parameter_scope::current); it != var::prms.end(parameter_scope::current); it++) {
        if (it->second.get_var()) {
            cnome_symbols.erase(it->second.get_var()->get_value().begin(), it->second.get_var()->get_value().end());
        }
    }
}

void cancelTmplPrmVar(iterator first, iterator last) {
    for (parameter_scope::level_const_iterator it = var::tmplPrms.begin(parameter_scope::current); it != var::tmplPrms.end(parameter_scope::current); it++) {
        if (it->second.get_var()) {
            cnome_symbols.erase(it->second.get_var()->get_value().begin(), it->second.get_var()->get_value().end());
        }
    }
}

rule_t isSpecialToken(NOTHING, false);
rule_t isNotSpecialToken(EPSILON, false);
rule_t CLASS_NAME_HELPER=NOTHING;
rule_t ENUM_NAME_HELPER=NOTHING;
rule_t TYPEDEF_NAME_HELPER=NOTHING;
rule_t NAMESPACE_ALIAS_HELPER=NOTHING;
rule_t ORIGINAL_NAMESPACE_NAME_HELPER=NOTHING;
rule_t TEMPLATE_NAME_HELPER=NOTHING;

void last_Identifier(iterator first, iterator last) {
    CLASS_NAME_HELPER=NOTHING;
    ENUM_NAME_HELPER=NOTHING;
    TYPEDEF_NAME_HELPER=NOTHING;
    NAMESPACE_ALIAS_HELPER=NOTHING;
    ORIGINAL_NAMESPACE_NAME_HELPER=NOTHING;
    TEMPLATE_NAME_HELPER=NOTHING;
    
    if (first->get_annotation()) {
        identifier_annotation* id_ann = dynamic_cast<identifier_annotation*>(first->get_annotation().get());
        if (id_ann->get_id_zone() == var::identifierZone.get_zone()) {
            symbol::identifierType id_type = id_ann->get_id_type();
            if (isEnableHandleTypeDef && id_ann->get_symbol_item_ptr()) {
                itSymbolItem it = cnome_symbols.find(id_ann->get_symbol_item_ptr()->to_str());
                handleTypeDefSymbol(it);
                if (it == cnome_symbols.end()) {
                    id_type = id_ann->get_id_type();
                }
            }
            if (id_type == symbol::NONE) {
                isSpecialToken=NOTHING;
                isNotSpecialToken=EPSILON;
            } else {
                isSpecialToken=EPSILON;
                isNotSpecialToken=NOTHING;
                switch (id_type) {
                case symbol::T_CLASS_NAME:
                    {
                    if (id_ann->get_symbol_item_ptr()) {
                        itSymbolItem it = cnome_symbols.find(id_ann->get_symbol_item_ptr()->to_str());
                        if (it == cnome_symbols.end()) {
                            CLASS_NAME_HELPER=EPSILON;
                        }
                        else {
                            handle_typdef_struct_X_X(it);
                        }
                    }
                    else {
                        CLASS_NAME_HELPER=EPSILON;
                    }
                    }
                    break;
                case symbol::T_ENUM_NAME:
                    ENUM_NAME_HELPER=EPSILON;
                    break;
                case symbol::T_ORIGINAL_NAMESPACE_NAME:
                    ORIGINAL_NAMESPACE_NAME_HELPER=EPSILON;
                    break;
                case symbol::T_TEMPLATE_NAME:
                    TEMPLATE_NAME_HELPER=EPSILON;
                    break;
                case symbol::T_NAMESPACE_ALIAS:
                    NAMESPACE_ALIAS_HELPER=EPSILON;
                    break;
                case symbol::T_TYPEDEF_NAME:
                    TYPEDEF_NAME_HELPER=EPSILON;
                    break;
		default:
		    break;
                }
            }
            return;
        }
    }

    bool isQualifiedId = last == iterator::end ? false : *last == T_COLON_COLON;
    symbol::identifierType id_type = symbol::NONE;
    std::string val;
    sblToStr(first, last, val);

    std::string curScope;
    get_scope(curScope, val.c_str());
#if defined(CNOME_DEBUG)
    std::cout << "last_Identifier: val: " << val << endl;
    std::cout << "last_Identifier: curScope: " << curScope << endl;
#endif
    
    itSymbolItem it = cnome_symbols.end();
    symbol lstTk(T_FIRST_TOKEN, first.get_cnome_position());
	size_t suffixSz = var::identifierZone.get_zone() != identifier_zone::var_specifier || isQualifiedId ? val.size() : curScope.size();
    scopesFromStr scopes(curScope, suffixSz);
    while (scopes.next_scope().size()) {
#if defined(CNOME_DEBUG)
        std::cout << "last_Identifier: scopes.current_scope() : " << scopes.current_scope();
#endif
        it = cnome_symbols.find_smallest(scopes.current_scope());
#if defined(CNOME_DEBUG)
        std::cout << " : " << (it != cnome_symbols.end()? (string("found : ") + it->second->to_str()).c_str(): "not found") << endl;
#endif
        bool isMtdImplicitInfered = false;
        // Verify if we have a full or partial match. For partial match verify if it is a method name.
        if (it != cnome_symbols.end()) {
            if (it->first != scopes.current_scope()) { // Partial match
                if (it->first.size() <= scopes.current_scope().size()) {
                    // TODO (alb): Verify if it is OK go to next scope in all situations
                    //continue;
                    if (!isQualifiedId || scopes.current_scope().substr(0, it->first.size()) != it->first) {
                        it = cnome_symbols.end();
#if defined(CNOME_DEBUG)
                        std::cout << "last_Identifier: cancel item found: its key is lesser than the current scope" << endl;
#endif
                    }
                }
                else if (it->first.substr(0,scopes.current_scope().size()) != scopes.current_scope()) {
                    //continue;
                    it = cnome_symbols.end();
#if defined(CNOME_DEBUG)
                    std::cout << "last_Identifier: cancel item found: its key isn't a preffix of the current scope" << endl;
#endif
                }
                else if ( *(it->second) != T_IDENTIFIER ) {
                    //continue;
                    it = cnome_symbols.end();
#if defined(CNOME_DEBUG)
                    std::cout << "last_Identifier: cancel item found: it isn't a identifier" << endl;
#endif
                }
                else if ( operator ==(last, iterator::end) || *last != T_LEFTPAREN || *last != T_LESS ) {
                    //continue;
                    it = cnome_symbols.end();
#if defined(CNOME_DEBUG)
                    std::cout << "last_Identifier: cancel item found: next token isn't a left parenthesis '(' " << endl;
#endif
                }
                else if ( it->second->get_symbol_type() != symbol::method ) {
                    itSymbolItem it2 = it;
                    isMtdImplicitInfered = false;
                    do {
                        isMtdImplicitInfered =    !isalpha(it2->first[scopes.current_scope().size()])
                                               && it2->first[scopes.current_scope().size()]!='_' 
                                               && it->second->get_symbol_type()==symbol::method; 
                        it2++;
                    } while (    !isMtdImplicitInfered && it2 != cnome_symbols.end() 
                              && it2->first.size() > scopes.current_scope().size() 
                              && it2->first.substr(0,scopes.current_scope().size()) == scopes.current_scope());
                    if (!isMtdImplicitInfered) {
                        //continue;
                        it = cnome_symbols.end();
                    }
#if defined(CNOME_DEBUG)
                    std::cout << "last_Identifier: cancel item found: it isn't a method or the next character is alpha" << endl;
#endif
                }
                else if ( it->second->get_identifier_type() == symbol::T_TEMPLATE_NAME ) {
                    isMtdImplicitInfered = false;
                }
            }
        }
        if (isEnableHandleTypeDef)
            handleTypeDefSymbol(it);
        if (isMtdImplicitInfered && isCtorDeclWithoutParent(scopes.current_scope())) {
            isSpecialToken=EPSILON;
            isNotSpecialToken=NOTHING;
            CLASS_NAME_HELPER=EPSILON;
            id_type = symbol::T_CLASS_NAME;
        }
        else if (    lstTk==T_FIRST_TOKEN 
                  && (    it == cnome_symbols.end() 
                       || (    *(it->second) == T_IDENTIFIER 
                            && it->second->get_identifier_type()==symbol::NONE)
                     ) 
                ) {
            isSpecialToken=NOTHING;
            isNotSpecialToken=EPSILON;
        }
        else if (     it != cnome_symbols.end() 
                   && (    ( *(it->second) == T_IDENTIFIER && it->second->get_identifier_type()!=symbol::NONE )
                        || it->second->get_symbol_type() == symbol::keyword  // HandleTypeDef get a builtin type
                      )
                ) {
            isSpecialToken=EPSILON;
            isNotSpecialToken=NOTHING;
            switch(id_type = it->second->get_identifier_type()) {
                case symbol::T_CLASS_NAME:
                    handle_typdef_struct_X_X(it);
                    break;
                case symbol::T_ENUM_NAME:
                    ENUM_NAME_HELPER=EPSILON;
                    break;
                case symbol::T_TYPEDEF_NAME:
                    TYPEDEF_NAME_HELPER=EPSILON;
                    break;
                case symbol::T_NAMESPACE_ALIAS:
                    NAMESPACE_ALIAS_HELPER=EPSILON;
                    break;
                case symbol::T_ORIGINAL_NAMESPACE_NAME:
                    ORIGINAL_NAMESPACE_NAME_HELPER=EPSILON;
                    break;
                case symbol::T_TEMPLATE_NAME:
                  /*  if (    isEnableTemplateName 
                         && it->second->get_symbol_type()!=symbol::method )  {  // Template name relate to a class or a method
                        CLASS_NAME_HELPER=EPSILON;
                        id_type = symbol::T_CLASS_NAME;
                    }
                    else*/
                        TEMPLATE_NAME_HELPER=EPSILON;
                    break;
                default:
                    if (it->second->get_symbol_type() == symbol::keyword) {
                        TYPEDEF_NAME_HELPER=EPSILON;
                        id_type = symbol::T_TYPEDEF_NAME;
                    }
                    break;
            }
            switch(lstTk.get_identifier_type()) {
                case symbol::T_CLASS_NAME:
                    if (it->second->get_identifier_type()!=symbol::T_CLASS_NAME) {
                        CLASS_NAME_HELPER=NOTHING;
                    }
                    break;
                case symbol::T_ENUM_NAME:
                    if (it->second->get_identifier_type()!=symbol::T_ENUM_NAME) {
                        ENUM_NAME_HELPER=NOTHING;
                    }
                    break;
                case symbol::T_TYPEDEF_NAME:
                    if (it->second->get_identifier_type()!=symbol::T_TYPEDEF_NAME) {
                        TYPEDEF_NAME_HELPER=NOTHING;
                    }
                    break;
                case symbol::T_NAMESPACE_ALIAS:
                    if (it->second->get_identifier_type()!=symbol::T_NAMESPACE_ALIAS) {
                        NAMESPACE_ALIAS_HELPER=NOTHING;
                    }
                    break;
                case symbol::T_ORIGINAL_NAMESPACE_NAME:
                    if (it->second->get_identifier_type()!=symbol::T_ORIGINAL_NAMESPACE_NAME) {
                        ORIGINAL_NAMESPACE_NAME_HELPER=NOTHING;
                    }
                    break;
                case symbol::T_TEMPLATE_NAME:
                    /*
                    if (it->second->get_identifier_type()!=symbol::T_TEMPLATE_NAME) {
                        if (    isEnableTemplateName 
                            && it->second->get_symbol_type()!=symbol::method ) { // Template name relate to a class or a method
                            CLASS_NAME_HELPER=NOTHING;
                        }
                        else {*/
                            TEMPLATE_NAME_HELPER=NOTHING;
                        //}
                    //}
                    break;
		default:
		    break;
            }
            lstTk = *it->second;
        }
    }
#if defined(CNOME_DEBUG)
    std::cout << "last_Identifier: var::tmplPrms.size() = " << var::tmplPrms.size() << endl;
#endif
    identifier_annotation* id_ann = 0;
    if (it == cnome_symbols.end() && var::tmplPrms.size()) { 
        lvlConstItPrms its = findInTmplPrms(val.c_str());
        if (its != var::tmplPrms.end(0)) {
            id_ann = new identifier_annotation(*dynamic_cast<identifier_annotation*>(its->second.get_type()->get_annotation().get()));
            id_ann->set_id_type(symbol::T_CLASS_NAME);
            // record reference
            id_ann->get_symbol_item_ptr()->get_references()[first] = var::scope.size() ? var::scope.back() : symbolPtr();
            isSpecialToken=EPSILON;
            isNotSpecialToken=NOTHING;
            CLASS_NAME_HELPER=EPSILON;
        }
    }
    if (!id_ann) {
        if (it != cnome_symbols.end()) {
            id_ann = new identifier_annotation(it->second, id_type);
            // record reference
            id_ann->get_symbol_item_ptr()->get_references()[first] = var::scope.size() ? var::scope.back() : symbolPtr();
        }
        else {
            id_ann = new identifier_annotation(symbolPtr(), id_type);
        }
    }
    id_ann->set_id_zone(var::identifierZone.get_zone());
    first->set_annotation(boost::shared_ptr<cnome::wave::cpplexer::token_annotation>(static_cast<cnome::wave::cpplexer::token_annotation*>(id_ann)));
}

void cancelDecl(iterator first, iterator last) {
#if defined(CNOME_DEBUG)
    std::cout << "cancelDecl: Canceling declaration!!!" << std::endl;
#endif
}

void error_Not_Declared(iterator first, iterator last) {
    std::string val;
    sblToStr(first, last, val);
    static string msg = "";
    msg = msg + val.c_str() + " isn't a valid class or namespace name.";
    std::cerr << std::endl << msg<< std::endl;
    std::cerr 
              << first->get_position().get_file() << "(" 
              << first->get_position().get_line() << ','
              << first->get_position().get_column() <<")"
              << std::endl;
    boost::spirit::classic::throw_(first, static_cast<const char*>(msg.c_str()));
}

void debug_point(iterator first, iterator last) {
    std::string val;
    for (iterator itv=first;itv!=last;itv++)
        val += itv->get_value().c_str();
    std::string curScope;
    get_scope(curScope, val.c_str());

#if defined(CNOME_DEBUG)
    std::cout << "debug_point: " << curScope << std::endl;
#endif  
}

void newTypeSpc(iterator first, iterator last) {
    if (first == last)
        return;

    size_t suffixSize;
    std::string val;
    adornersT adrns;
    sblToStr(first, last, val, adrns, suffixSize);
    appendAdorners(val, adrns, suffixSize);

    scopesFromStr scopes(val, suffixSize);
    while (scopes.next_scope().size()) {
        itSymbolItem it; 
        if ((it = findTypeDecl(scopes.current_scope(), first)) != cnome_symbols.end()) {
#if defined(CNOME_DEBUG)
            std::cout << "newTypeSpc: scopes.current_scope() = " << scopes.current_scope() << endl;
            std::cout << "newTypeSpc: curScp = " << val << endl;
#endif
            // TODO: Verify if the solution bellow will work 
            scopeT lscp;
            for (symbolPtr it2=it->second; it2; it2=it2->get_scope()) {
                string val = it2->to_str();
                appendAdorners(val, it2->get_adorners());

                itSymbolItem it3 = cnome_symbols.find(val);
                if (it3!=cnome_symbols.end())
                    lscp.push_back(it3->second);
                else
                    lscp.push_back(it2);
            }
            while (lscp.size()) {
                symbolPtr aux = lscp.back();
                var::typeDecl.push_back(aux);
                lscp.pop_back();
            }

            return;
        }    
    }

    // A new symbol was found but it isn't already declared
#if defined(CNOME_DEBUG)
            std::cout << "newTypeSpc: val = " << val << endl;
#endif
    if (*first == T_INLINE)
        return;
    token_t tk = *first;
    symbolPtr smb = symbolPtr(new symbol(tk, symbol::other, first.get_cnome_position()));
    smb->set_adorners(adrns);
    var::typeDecl.push_back(smb);
}

bool isEnableHandleTypeDef = false;

void enableHandleTypeDef(iterator first, iterator last) {
    isEnableHandleTypeDef = true;
}

void disableHandleTypeDef(iterator first, iterator last) {
    isEnableHandleTypeDef = false;
}

bool isEnableTemplateName = false;

void enableTemplateName(iterator first, iterator last) {
    isEnableTemplateName = true;
}

void disableTemplateName(iterator first, iterator last) {
    isEnableTemplateName = false;
}
  
rule_t LASTSMBFLOPISGREATER = NOTHING;

void isLOpLastSmbGrt(iterator first, iterator last) {
    iterator prev;
    for (prev = first; first != last; first++)
        prev = first;
    if (prev == last || *prev != T_GREATER)
        LASTSMBFLOPISGREATER = NOTHING;
    else
        LASTSMBFLOPISGREATER = EPSILON;
}


void inFunction_body(iterator first, iterator last) {
    sglUtil::instance()->set_state(sglUtil::inside_function_body);
    adjustTmplPrms(first, last);
}

void outFunction_body(iterator first, iterator last) {
    sglUtil::instance()->set_state(sglUtil::outside_function_body);
}
  
void new_dcl_spc(iterator first, iterator last) {
    adornersT adrns;
    bool needScope = false;
    bool isTypedef = false;
    bool isTemplate = false;
    bool isStatic = false;
    bool fndTypename = false;
    bool fndTmplPrm = false;
    bool stopColleting = false;
    std::string val;
    iterator lclF=first;
    iterator lclL=last;
    iterator prev=last;
    token_t tk;
    for(bool goOut=false,canGoOut=false;!goOut&&lclF!=lclL;lclF++) {
        switch(tk = *lclF) {
            case T_TYPEDEF:
                {
                // TODO: Handle typedef???
                symbolPtr tmp = symbolPtr(new symbol(*lclF, symbol::other, lclF.get_cnome_position()));
                var::dcl_spc.push_back(tmp);
                isTypedef = true;
                }
                break;
            case T_TYPENAME:
                {
                // TODO: Handle typedef???
                symbolPtr tmp = symbolPtr(new symbol(*lclF, symbol::other, lclF.get_cnome_position()));
                var::dcl_spc.push_back(tmp);
                fndTypename = true;
                }
                break;
            case T_STATIC: 
                {
                // TODO: Handle typedef???
                symbolPtr tmp = symbolPtr(new symbol(*lclF, symbol::other, lclF.get_cnome_position()));
                var::dcl_spc.push_back(tmp);
                isStatic = true;
                }
                break;
            case T_SIGNED:
            case T_UNSIGNED:
            case T_CONST:
            case T_AND:
            case T_STAR:
                // TODO: Handle signed and unsigned keywords correctly
                val += lclF->get_value().c_str();
                first=lclF;
                canGoOut=true;
                break;
            case T_CHAR:
            case T_WCHART:
            case T_SHORT:
            case T_INT:
            case T_LONG:
                if (*prev == T_SIGNED || *prev == T_UNSIGNED || *prev == T_CONST || *prev == T_LONG || *prev == T_SHORT)
                    val += " ";
                val += lclF->get_value().c_str();
                first=lclF;
                canGoOut=true;
                break;
            case T_BOOL:
            case T_FLOAT:
            case T_VOID:
                if (*prev == T_CONST)
                    val += " ";
                val += lclF->get_value().c_str();
                first=lclF;
                canGoOut=true;
                break;
            case T_DOUBLE:
                if (*prev == T_CONST || *prev == T_LONG)
                    val += " ";
                val += lclF->get_value().c_str();
                first=lclF;
                canGoOut=true;
                break;
            case T_IDENTIFIER:
                {
                    if (!stopColleting) {
                        val += lclF->get_value().c_str();
                    }
                    lvlConstItPrms its = findInTmplPrms(val.c_str());
                    fndTmplPrm = its != var::tmplPrms.end(0);
                    needScope = !fndTmplPrm;
                    first=lclF;
                    canGoOut=true;
                }
                break;
            case T_LESS:
            case T_GREATER:
                val += lclF->get_value().c_str();
                isTemplate = true;
                break;
            case T_COLON_COLON:
                // TODO: Verify if it will be necessary test "."
                val += lclF->get_value().c_str();
                break;
            case T_COLON:
                stopColleting = true; // Probably we have a declaration "class a: b ...", where
                                      // "a: b..." is passed to this function
                goOut=true;
                break;
            case T_LEFTBRACE:
                goOut = true;
                break;
            case T_LEFTPAREN:
                if (canGoOut)
                    goOut=true;
                break;
	    default:
	        break;
        }
        prev = lclF;
    }
    std::size_t valLen = val.size();
    if ((isTypedef || isStatic) && !val.size())
        return;

    std::size_t curScpLen = 0;
    std::string curScp;
    if (needScope) {
        get_scope(curScp,val.c_str());
        val = curScp;
        curScpLen = curScp.size();
    }

    itSymbolItem itF = cnome_symbols.end();
    scopesFromStr scopes(val, valLen);
    while (scopes.next_scope().size()) {

        string auxScope = scopes.current_scope();
        if (isTemplate) // TODO: Fix this temporary solution
            auxScope = auxScope.substr(0, auxScope.find_first_of('<'));

        itSymbolItem it;
        if (    (it = cnome_symbols.find(auxScope)) != cnome_symbols.end() ) {
            token_t tk(*first);
            if (adrns.size()) {  // Verify if adorners change the type
                auxScope = scopes.current_scope();
                for (it_adornersT itad = adrns.begin(); itad!=adrns.end(); itad++)
                    auxScope += string(" ") + itad->get_value().c_str();
                itSymbolItem it2;
                if ((it2 = cnome_symbols.find_smallest(auxScope)) != cnome_symbols.end())
                    it = it2;
                
                size_t idx;
                for(idx=auxScope.size();idx>0&&auxScope[idx-1]!=':'&&auxScope[idx-1]!='$';idx--);
                tk.set_value(auxScope.substr(idx).c_str());
                symbolPtr smb = symbolPtr(new symbol(tk, it->second->get_symbol_type(), first.get_cnome_position()));
                smb->set_scope(get_symbol_scope(auxScope.c_str())!=cnome_symbols.end()?get_symbol_scope(auxScope.c_str())->second:symbolPtr(static_cast<symbol*>(0)));
                smb->set_symbol_status(symbol::defined);
                smb->set_adorners(adrns);
                smb->set_identifier_type(it->second->get_identifier_type());
                cnome_symbols[smb->to_str()] = smb;
                it = cnome_symbols.find(smb->to_str()); // Find it again
            }
            itF = it;

#if defined(CNOME_DEBUG)
            std::cout << "new_dcl_spc: scopes.current_scope() = " << scopes.current_scope() << endl;
            std::cout << "new_dcl_spc: curScp = " << curScp << endl;
#endif
        }    
    }

    if (itF != cnome_symbols.end()) {
        var::dcl_spc.push_back(itF->second);
        return;
    }
    // Try more
    // Consider that val always starts with "::"
    std::size_t auxLen = curScpLen>valLen?curScpLen-valLen:valLen;
    for (std::size_t idx = val.find_first_of(":$",2); 
        idx != val.npos && idx < auxLen; 
        idx = (idx != val.npos)?val.find_first_of(":$",idx+(val[idx]==':'?2:1)):
               val.npos) {
        std::string auxScope;
        if (idx != val.npos)
            auxScope = val.substr(0,idx+(val[idx]==':'?2:1))+(curScpLen>valLen?val.substr(curScpLen-valLen):"");
        else
            auxScope = val;
        itSymbolItem it;
        if (    (it = cnome_symbols.find(auxScope)) != cnome_symbols.end() ) {
            token_t tk(*first);
            if (adrns.size()) {  // Verify if adorners change the type
                for (it_adornersT itad = adrns.begin(); itad!=adrns.end(); itad++)
                    auxScope += ' ' + *itad;
                 itSymbolItem it2;
                if ((it2 = cnome_symbols.find_smallest(auxScope.c_str())) != cnome_symbols.end())
                    it = it2;
                else {
                    size_t idx;
                    for(idx=auxScope.size();idx>0&&auxScope[idx-1]!=':'&&auxScope[idx-1]!='$';idx--);
                    tk.set_value(auxScope.substr(idx).c_str());
                    symbolPtr smb = symbolPtr(new symbol(tk, it->second->get_symbol_type(), first.get_cnome_position()));
                    smb->set_scope(get_symbol_scope(auxScope.c_str())!=cnome_symbols.end()?get_symbol_scope(auxScope.c_str())->second:symbolPtr(static_cast<symbol*>(0)));
                    smb->set_symbol_status(symbol::defined);
                    smb->set_adorners(adrns);
                    smb->set_identifier_type(it->second->get_identifier_type());
                    cnome_symbols[smb->to_str()] = smb;
                    it = cnome_symbols.find(smb->to_str()); // Find it again
                }
            }
            itF = it;

#if defined(CNOME_DEBUG)
            std::cout << "new_dcl_spc: auxScope = " << auxScope << endl;
            std::cout << "new_dcl_spc: curScp = " << curScp << endl;
#endif
        }    
    }

    // A new symbol was found but it isn't already declared
    if (itF != cnome_symbols.end())
        var::dcl_spc.push_back(itF->second);
    else {
#if defined(CNOME_DEBUG)
            std::cout << "new_dcl_spc: val = " << val << endl;
            std::cout << "new_dcl_spc: curScp = " << curScp << endl;
#endif
        token_t tk = *first;
        if (val.size()>2 && val[0] == ':' && val[1] == ':')
            val = val.substr(2);
        tk.set_value(val.c_str());
        symbolPtr smb = symbolPtr(new symbol(tk, fndTmplPrm?symbol::internal:symbol::other, first.get_cnome_position()));
        smb->set_adorners(adrns);
        var::dcl_spc.push_back(smb);
        if (fndTypename && !fndTmplPrm) {  // To avoid collision of the name of the template parameter it isn't added to the symbol table
            smb->set_identifier_type(symbol::T_CLASS_NAME);
            cnome_symbols[smb->to_str()] = smb;
        }
    }
}

rule_t TYPE_DECL_VALID_HELP = EPSILON;

void typDclValid(iterator first, iterator last) {
    if (!var::dcl_spc.size()) {   // Current type sequence is empty
        TYPE_DECL_VALID_HELP = EPSILON;
        return;
    }
    bool fndLong = false;
    bool fndShort = false;
    bool fndInline = false;
    bool fndVirtual = false;
    bool fndBuildinType = false;
    bool fndUserType = false;
    bool fndSigned = false;
    bool fndUnsigned = false;
    bool fndTypedef = false;
    bool fndExtern = false;
    bool fndStatic = false;
    bool fndFriend = false;
    //bool fndTemplate = false;
    bool fndMutable = false;
    bool fndExplicit = false;
    bool fndTypename = false;
    int insideTemplateDecl = 0;
    std::string val;
    std::string aux;
    boost::wave::token_id prevTk=T_FIRST_TOKEN;
    for (scopeT::const_iterator it = var::dcl_spc.begin(); it != var::dcl_spc.end(); it++) {
        token_t tk;
        switch(tk = **it) {
            case T_LESS:
                insideTemplateDecl++;
                break;
            case T_GREATER:
                insideTemplateDecl--;
                break;
            case T_EXTERN:
                if (    fndInline || fndVirtual || fndBuildinType || fndUserType || fndSigned
                     || fndUnsigned || fndTypedef ) {
                    // Error: extern must be the first token in type declaration and can't be repeated
                    // and mixed with virtual and typedef
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else
                    TYPE_DECL_VALID_HELP = EPSILON;
                fndExtern = true;
                break;
            case T_INLINE:
                if (    fndInline || fndVirtual || fndBuildinType || fndUserType || fndSigned
                     || fndUnsigned || fndTypedef )  { // TODO: verify if extern can be mixed with inline.
                    // Error: inline must be the first token in type declaration and can't be repeated
                    // and mixed with virtual and typedef
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else
                    TYPE_DECL_VALID_HELP = EPSILON;
                fndInline = true;
                break;
            case T_EXPLICIT: // TODO: Validate the explicit combination with the others.
                TYPE_DECL_VALID_HELP = EPSILON;
                fndExplicit = true;
                break;
            case T_VIRTUAL:
                if (    fndInline || fndVirtual || fndBuildinType || fndUserType || fndSigned
                     || fndUnsigned || fndTypedef) { // TODO: verify if extern can be mixed with virtual.
                    // Error: virtual must be the first token in type declaration and can't be repeated
                    // and mixed with inline and typedef
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else
                    TYPE_DECL_VALID_HELP = EPSILON;
                fndVirtual = true;
                break;
            case T_TYPEDEF:
                if (    fndInline || fndVirtual || fndBuildinType || fndUserType || fndSigned
                     || fndUnsigned || fndTypedef) { // TODO: verify if extern can be mixed with typedef.
                    // Error: typedef must be the first token in type declaration and can't be repeated
                    // and mixed with inline and virtual
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else
                    TYPE_DECL_VALID_HELP = EPSILON;
                fndTypedef = true;
                break;
            case T_STATIC:
                if (    fndStatic || fndVirtual || fndBuildinType || fndUserType || fndSigned
                     || fndUnsigned ) { // TODO: Verify better if there are more conditions here, for exemplo mixed with Typedef 
                    // Error: static can't be repeated and must be before buildin and user types, can't be mixed
                    // with virtual
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else
                    TYPE_DECL_VALID_HELP = EPSILON;
                fndStatic = true;
                break;
            case T_FRIEND:
                if (    fndFriend || fndVirtual || fndBuildinType || fndUserType || fndSigned
                     || fndUnsigned ) { // TODO: Verify better if there are more conditions here, for exemplo mixed with Typedef 
                                      //       and static
                    // Error: friend can't be repeated and must be before buildin and user types, can't be mixed
                    // with virtual - 
                    // TODO: verify in virtual case condition the fndFriend and fndStatic
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else
                    TYPE_DECL_VALID_HELP = EPSILON;
                fndFriend = true;
                break;
            case T_MUTABLE:
                if (fndMutable || fndVirtual || fndBuildinType || fndUserType || fndSigned
                     || fndUnsigned ) {
                    // Error: mutable can't be repeated and must be before buildin and user types, can't be mixed
                    // with virtual - 
                    // TODO: verify in virtual case condition the fndFriend and fndStatic
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                fndMutable = true;
                break;
            case T_INT:
            case T_CHAR:
                if (fndBuildinType || fndUserType) {
                    // Error: the builtin type can't be repeated and mixed with user type
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else
                    TYPE_DECL_VALID_HELP = EPSILON;
                fndBuildinType = true;
                break;
            case T_SHORT:
                if (fndBuildinType || fndUserType) {
                    // Error: the builtin type can't be repeated and mixed with user type
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else
                    TYPE_DECL_VALID_HELP = EPSILON;
                fndShort = true;
                break;
            case T_LONG:
                if (fndBuildinType || fndUserType) {
                    // Error: the builtin type can't be repeated and mixed with user type
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else
                    TYPE_DECL_VALID_HELP = EPSILON;
                fndLong = true;
                break;
            case T_WCHART:
            case T_FLOAT:
            case T_VOID:
            case T_BOOL:
                if (fndBuildinType || fndUserType || fndSigned || fndUnsigned || fndLong || fndShort) {
                    // Error: this builtin type can't be repeated and mixed with user type and
                    // mixed with signed and unsigned
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else
                    TYPE_DECL_VALID_HELP = EPSILON;
                fndBuildinType = true;
                break;
            case T_DOUBLE:
                if (fndBuildinType || fndUserType || fndSigned || fndUnsigned) {
                    // Error: this builtin type can't be repeated and mixed with user type and
                    // mixed with signed and unsigned
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else
                    TYPE_DECL_VALID_HELP = EPSILON;
                fndBuildinType = true;
                break;
            case T_UNSIGNED:
                if (    fndBuildinType || fndUserType || fndSigned
                     || fndUnsigned ) {
                    // Error: unsigned must be before buildin types in type declaration and can't be repeated
                    // and mixed with user type and signed
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else
                    TYPE_DECL_VALID_HELP = EPSILON;
                fndUnsigned = true;
                break;
            case T_SIGNED:
                if (    fndBuildinType || fndUserType || fndSigned
                     || fndUnsigned ) {
                    // Error: signed must be before buildin types in type declaration and can't be repeated
                    // and mixed with user type and unsigned
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else
                    TYPE_DECL_VALID_HELP = EPSILON;
                fndSigned = true;
                break;
            case T_IDENTIFIER:
                if ( fndUserType ) {
                    // Error: the user type can't be repeat in normal case
                    TYPE_DECL_VALID_HELP = NOTHING;
                    if ( !fndTypedef )              // When we have "typedef struct a{...} a;" the parser can wrongly 
                    return;
                }
                else if ( fndUserType || fndSigned || fndUnsigned || fndBuildinType || fndExplicit || fndLong || fndShort) {
                    // Error: the user type can't and mixed with buildin type 
                    // and mixed with signed and unsigned. Explicit only can be used to constructors
                    // and a constructor isn't a type
                    TYPE_DECL_VALID_HELP = NOTHING;
                    return;
                }
                else {
                    itSymbolItem it2;
                    if ((it2 = cnome_symbols.find((*it)->to_str())) == cnome_symbols.end()) {
                        lvlConstItPrms its = findInTmplPrms((*it)->to_str());
                        if (its == var::tmplPrms.end(0)) {
                            TYPE_DECL_VALID_HELP = NOTHING;
                        }
                        else {
                            TYPE_DECL_VALID_HELP = EPSILON;
                        }
                    }
                    else
                        if (it2->second->get_symbol_type() != symbol::method) {
                            if (isCtorDecl((*it)->to_str()))
                                TYPE_DECL_VALID_HELP = NOTHING;
                            else
                                TYPE_DECL_VALID_HELP = EPSILON;
                        }
                        else
                            TYPE_DECL_VALID_HELP = NOTHING;
                }
                fndUserType = true;
                break;
            case T_AND:
            case T_STAR:
                TYPE_DECL_VALID_HELP = NOTHING;
                break;
            case T_CONST: // TODO: handle const correctly
                TYPE_DECL_VALID_HELP = EPSILON;
                break;
            case T_CLASS:
            case T_ENUM:   // TODO: Implement a test to avoid the mix and repeat of this tokens
            case T_STRUCT: // TODO: handle "struct a* b;" declaration better
            case T_UNION:
                break;
            case T_COLON_COLON:
                    val += (*it)->get_value().c_str();
                break;
            case T_TYPENAME: // TODO: Verify the valid combination for typename. ALB 25may06
                fndTypename = true;
                break;
            default:  // Invalid type declaration
                TYPE_DECL_VALID_HELP = NOTHING;
                return;
                break;
        }
        prevTk = **it;
        aux = getSuffixForSymbol(**it);
    }
}

rule_t TYPE_DECL_VALID=EPSILON[&typDclValid] >> TYPE_DECL_VALID_HELP;

void cancelLastPrm(iterator first, iterator last) {
    var::prms.cancelLastPrm();
}

void declareTmplPrms(iterator first, iterator last) {
    if (var::tmplPrms.size()) {
        var::tmplSbl = var::mthScope;
    }
    // Implicity declares the template parameters
    for (parameter_scope::level_const_iterator it = var::tmplPrms.begin(parameter_scope::current); it != var::tmplPrms.end(parameter_scope::current); ++it) {
        if (!it->second.is_var_null()) {
           symbolPtr sybIts = dynamic_cast<parameter_annotation*>(it->second.get_type()->get_annotation().get())->get_symbol_item_ptr();
           sybIts->set_scope(var::tmplSbl);
           sybIts->set_identifier_type(symbol::T_CLASS_NAME); // TODO: Change to T_TEMPLATE_PARAMETER e modify code to support it
           cnome_symbols[sybIts->to_str()] = sybIts;
           var::tmplSbl->add(sybIts);
#if defined(CNOME_DEBUG)
           std::cout << "declareTmplPrms: Template Parameter: " << sybIts->to_str() << std::endl;
#endif
        }
        else {
            if (!it->second.get_var() || it->second.get_var()->get_annotation()->get_tag() != PARAMETERANNOTATION)
                continue;
            parameter_annotation* annotation = dynamic_cast<parameter_annotation*>(it->second.get_var()->get_annotation().get()) ;
            symbolPtr sybItv = annotation->get_symbol_item_ptr();
            sybItv->set_scope(var::tmplSbl);
            // Uncomment line below and modify code to support it
            //sybItv->set_identifier_type(symbol::T_TEMPLATE_VARIABLE);
            cnome_symbols[sybItv->to_str()] = symbolPtr(sybItv);          // Add parameter to symbol table 
            var::tmplSbl->add(sybItv);
#if defined(CNOME_DEBUG)
            std::cout << "declareTmplPrms: Template Parameter Variable: " << sybItv->to_str() << std::endl;
#endif
        }
    }
}

void declareClassTmplPrms(iterator first, iterator last) {
    // Implicity declares the template parameters
    for (parameter_scope::level_const_iterator it = var::tmplPrms.begin(parameter_scope::next); it != var::tmplPrms.end(parameter_scope::next); ++it) {
        if (!it->second.is_var_null()) {
           symbolPtr sybIts = dynamic_cast<parameter_annotation*>(it->second.get_type()->get_annotation().get())->get_symbol_item_ptr();
           sybIts->set_scope(var::scope.back());
           sybIts->set_identifier_type(symbol::T_CLASS_NAME); // TODO: Change to T_TEMPLATE_PARAMETER e modify code to support it
           cnome_symbols[sybIts->to_str()] = sybIts;
           var::tmplSbl->add(sybIts);
#if defined(CNOME_DEBUG)
           std::cout << "declareTmplPrms: Template Parameter: " << sybIts->to_str() << std::endl;
#endif
        }
        else {
            if (it->second.get_var()->get_annotation()->get_tag() != PARAMETERANNOTATION)
                continue;
            parameter_annotation* annotation = dynamic_cast<parameter_annotation*>(it->second.get_var()->get_annotation().get()) ;
            symbolPtr sybItv = annotation->get_symbol_item_ptr();
            sybItv->set_scope(var::scope.back());
            // Uncomment line below and modify code to support ist
            //sybItv->set_identifier_type(symbol::T_TEMPLATE_VARIABLE);
            cnome_symbols[sybItv->to_str()] = symbolPtr(sybItv);          // Add parameter to symbol table 
            var::tmplSbl->add(sybItv);
#if defined(CNOME_DEBUG)
            std::cout << "declareTmplPrms: Template Parameter Variable: " << sybItv->to_str() << std::endl;
#endif
        }
    }
}

void addUsingDirective(iterator first, iterator last) {
    std::string val;
    for (iterator itv=first;itv!=last;itv++)
        val += itv->get_value().c_str();

    std::string curScope;
    get_scope(curScope, val.c_str());
#if defined(CNOME_DEBUG)
    std::cout << "addUsingDirective: val: " << val << endl;
    std::cout << "addUsingDirective: curScope: " << curScope << endl;
#endif

    scopesFromStr scopes(curScope, val.size());
    while (scopes.next_scope().size()) {
        itSymbolItem it;
        if ((it=cnome_symbols.find(scopes.current_scope())) != cnome_symbols.end()) {
            var::l_usgDrts.push_back(it);
#if defined(CNOME_DEBUG)
            std::cout << "addUsingDirective: scopes.current_scope() = " << scopes.current_scope() << endl;
#endif
            break;
        }    
    }
}

void rememberDeclaratorId(iterator first, iterator last) {
    var::lastDeclaratorId.first = first;
    var::lastDeclaratorId.second = last;
}
}} // namespace cnome { namespace actions {
